#include "Logger.h"
#include <map>
#include <log4cplus/logger.h>
#include <log4cplus/configurator.h>

class LoggerImpl
{
public:
	LoggerImpl(log4cplus::Logger logger)
	{
		m_Logger = logger;
	}
	~LoggerImpl()
	{
	}
	inline void Log(log4cplus::LogLevel ll, const std::string& rMessage, const char* szFileName, int nLine)
	{
		if (m_Logger.isEnabledFor(ll))
		{
			m_Logger.forcedLog(ll, rMessage, szFileName, nLine);
		}
	}
private:
	log4cplus::Logger m_Logger;
};

class CLogManager
{
public:
	inline static CLogManager & Instance()
	{
		static CLogManager sLogManager;
		return sLogManager;
	}
	Logger& GetLogger(const std::string& strName);
	inline Logger& GetDefaultLogger()
	{
		static Logger logger(new LoggerImpl(log4cplus::Logger::getRoot()));
		return logger;
	}
private:
	CLogManager();
	~CLogManager();
	std::map< std::string, Logger* > m_LoggerMap;
};
CLogManager::CLogManager()
{
	log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("log4cplus.properties"));
}
CLogManager::~CLogManager()
{
	std::map< std::string, Logger* >::iterator it = m_LoggerMap.begin();
	for (; it!= m_LoggerMap.end(); ++it)
	{
		delete it->second;
		it->second = 0;
	}
	m_LoggerMap.clear();
}
Logger& CLogManager::GetLogger(const std::string& strName)
{
	std::map< std::string, Logger* >::iterator it = m_LoggerMap.find(strName);
	if (it != m_LoggerMap.end())
	{
		return *(it->second);
	}
	else
	{
		Logger* pLogger = new Logger(new LoggerImpl(log4cplus::Logger::getInstance(strName)));
		m_LoggerMap.insert(std::pair< std::string, Logger* >(strName, pLogger));
		return *pLogger;
	}
}

Logger::Logger(LoggerImpl *pLoggerImpl)
{
	m_pLoggerImpl = pLoggerImpl;
}

Logger::~Logger()
{
	delete m_pLoggerImpl;
	m_pLoggerImpl = 0;
}

void Logger::Trace(const std::string& rMessage, const char* szFileName, int nLine)
{
	m_pLoggerImpl->Log(log4cplus::TRACE_LOG_LEVEL, rMessage, szFileName, nLine);
}

void Logger::Debug(const std::string& rMessage, const char* szFileName, int nLine)
{
	m_pLoggerImpl->Log(log4cplus::DEBUG_LOG_LEVEL, rMessage, szFileName, nLine);
}

void Logger::Info(const std::string& rMessage, const char* szFileName, int nLine)
{
	m_pLoggerImpl->Log(log4cplus::INFO_LOG_LEVEL, rMessage, szFileName, nLine);
}

void Logger::Warn(const std::string& rMessage, const char* szFileName, int nLine)
{
	m_pLoggerImpl->Log(log4cplus::WARN_LOG_LEVEL, rMessage, szFileName, nLine);
}

void Logger::Error(const std::string& rMessage, const char* szFileName, int nLine)
{
	m_pLoggerImpl->Log(log4cplus::FATAL_LOG_LEVEL, rMessage, szFileName, nLine);
}

Logger& Logger::GetInstance(const std::string& strName)
{
	return CLogManager::Instance().GetLogger(strName);
}

Logger& Logger::GetInstance()
{
	return CLogManager::Instance().GetDefaultLogger();
}
